/* export-settings-dialog.vala
 *
 * Copyright (C) 2010, 2011  Richard Talbot-Watkins
 * Copyright (C) 2010, 2011  Dave Jeffery
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * Authors:
 *  Richard Talbot-Watkins <richtw1@gmail.com>
 * 	Dave Jeffery <david.richard.jeffery@gmail.com>
 */

using Gtk;

/**
 * Export settings dialog box for Beeb Spriter.
 *
 * @author Richard Talbot-Watkins <richtw1@gmail.com>
 * @author Dave Jeffery <david.richard.jeffery@gmail.com>
 * @version 2010.0117
 * @since 0.1
 */
public class BeebSpriter.ExportSettingsDialog : Dialog {

	private RadioButton layout_row_major;
	private RadioButton layout_column_major;
	private RadioButton size_whole;
	private RadioButton size_break;
	private SpinButton break_across;
	private Label break_across_label;
	private SpinButton break_down;
	private Label break_down_label;
	private RadioButton transparency_colour_0;
	private RadioButton transparency_mask;
	private CheckButton header_checkbutton;
	private Entry syntax_entry;
	private Label syntax_label_1;
	private Label syntax_label_2;

	private SpriteSheet sprite_sheet;

	/**
	 * Constructor for the export settings dialog box.
	 */
	public ExportSettingsDialog (Window parent_window, SpriteSheet sprite_sheet) {
		this.sprite_sheet = sprite_sheet;

		title = _("Export settings");
		border_width = 5;
		icon = parent_window.icon;
		resizable = false;
		set_transient_for (parent_window);

		create_widgets ();
		initialise_widgets ();
		connect_signals ();
	}

	/**
	 * Creates the widgets that appear on the export settings dialog box.
	 */
	private void create_widgets () {
		var frame_vbox = new VBox (false, 22);

		/* Sprite layout frame. */
		var sprite_layout_frame = new Frame (null);
		sprite_layout_frame.shadow_type = ShadowType.NONE;
		var sprite_layout_label = new Label (_("<b>Sprite layout</b>"));
		sprite_layout_label.use_markup = true;
		sprite_layout_frame.set_label_widget (sprite_layout_label);
		var sprite_layout_alignment = new Alignment (0.5f, 0.5f, 1.0f, 1.0f);
		sprite_layout_alignment.left_padding = 12;
		var layout_vbox = new VBox (false, 0);
		var layout_group = new SList<RadioButton> ();
		layout_row_major = new RadioButton.with_label (
			layout_group, 
			_("Row major (good for character block aligned sprites)"));
		layout_column_major = new RadioButton.with_label (
			layout_row_major.get_group (), 
			_("Column major (for sprites to be plotted at any pixel line)"));
		layout_vbox.pack_start (layout_row_major);
		layout_vbox.pack_start (layout_column_major);
		sprite_layout_alignment.add (layout_vbox);
		sprite_layout_frame.add (sprite_layout_alignment);

		/* Sprite size frame. */
		var sprite_size_frame = new Frame (null);
		sprite_size_frame.shadow_type = ShadowType.NONE;
		var sprite_size_label = new Label (_("<b>Sprite size</b>"));
		sprite_size_label.use_markup = true;
		sprite_size_frame.set_label_widget (sprite_size_label);
		var sprite_size_alignment = new Alignment (0.5f, 0.5f, 1.0f, 1.0f);
		sprite_size_alignment.left_padding = 12;
		var size_vbox = new VBox (false, 0);
		var size_group = new SList<RadioButton> ();
		size_whole = new RadioButton.with_label (
			size_group, 
			_("Export sprites at their defined size"));
		size_break = new RadioButton.with_label (
			size_whole.get_group (), 
			_("Break sprites into smaller pieces of size:"));
		var break_alignment = new Alignment (0.5f, 0.5f, 1.0f, 1.0f);
		break_alignment.left_padding = 44;
		var break_vbox = new VBox (false, 0);
		var break_across_hbox = new HBox (false, 0);
		break_across = new SpinButton.with_range (1.0d, 10.0d, 1.0d);
		break_across.xalign = 1.0f;
		break_across_label = new Label (_("character blocks across"));
		break_across_hbox.pack_start (break_across, false, false, 0);
		break_across_hbox.pack_start (break_across_label, false, false, 8);
		var break_down_hbox = new HBox (false, 0);
		break_down = new SpinButton.with_range (1.0d, 10.0d, 1.0d);
		break_down.xalign = 1.0f;
		break_down_label = new Label (_("character blocks down"));
		break_down_hbox.pack_start (break_down, false, false, 0);
		break_down_hbox.pack_start (break_down_label, false, false, 8);
		break_vbox.pack_start (break_across_hbox);
		break_vbox.pack_start (break_down_hbox);
		break_alignment.add (break_vbox);
		size_vbox.pack_start (size_whole);
		size_vbox.pack_start (size_break);
		size_vbox.pack_start (break_alignment);
		sprite_size_alignment.add (size_vbox);
		sprite_size_frame.add (sprite_size_alignment);

		/* Transparency / masking frame. */
		var transparency_frame = new Frame (null);
		transparency_frame.shadow_type = ShadowType.NONE;
		var transparency_label = new Label (_("<b>Transparency / masking</b>"));
		transparency_label.use_markup = true;
		transparency_frame.set_label_widget (transparency_label);
		var transparency_alignment = new Alignment (0.5f, 0.5f, 1.0f, 1.0f);
		transparency_alignment.left_padding = 12;
		var transparency_vbox = new VBox (false, 0);
		var transparency_group = new SList<RadioButton> ();
		transparency_colour_0 = new RadioButton.with_label (
			transparency_group, 
			_("Export transparent pixels as colour 0"));
		transparency_mask = new RadioButton.with_label (
			transparency_colour_0.get_group (), 
			_("Export separate sprite mask"));
		transparency_vbox.pack_start (transparency_colour_0);
		transparency_vbox.pack_start (transparency_mask);
		transparency_alignment.add (transparency_vbox);
		transparency_frame.add (transparency_alignment);

		/* Header file generation frame. */
		var header_frame = new Frame (null);
		header_frame.shadow_type = ShadowType.NONE;
		var header_label = new Label (_("<b>Header file generation</b>"));
		header_label.use_markup = true;
		header_frame.set_label_widget (header_label);
		var header_alignment = new Alignment (0.5f, 0.5f, 1.0f, 1.0f);
		header_alignment.left_padding = 12;
		var header_vbox = new VBox (false, 0);
		header_checkbutton = new CheckButton.with_label (
							_("Export header information for named sprites"));
		var syntax_alignment = new Alignment (0.5f, 0.5f, 1.0f, 1.0f);
		syntax_alignment.left_padding = 22;
		syntax_alignment.right_padding = 4;
		syntax_alignment.top_padding = 11;
		var syntax_vbox = new VBox (false, 0);
		syntax_label_1 = 
			new Label (_("Syntax for defining a symbol in your assembler:"));
		syntax_label_2 = new Label (
			_("{n} = generated symbol name, {v} = unprefixed hex value"));
		syntax_label_1.xalign = 0.0f;
		syntax_label_2.xalign = 0.0f;
		var entry_alignment = new Alignment (0.5f, 0.5f, 1.0f, 1.0f);
		entry_alignment.left_padding = 22;
		entry_alignment.top_padding = 11;
		syntax_entry = new Entry ();
		entry_alignment.add (syntax_entry);
		syntax_vbox.pack_start (syntax_label_1);
		syntax_vbox.pack_start (syntax_label_2);
		syntax_vbox.pack_start (entry_alignment);
		syntax_alignment.add (syntax_vbox);
		header_vbox.pack_start (header_checkbutton);
		header_vbox.pack_start (syntax_alignment);
		header_alignment.add (header_vbox);
		header_frame.add (header_alignment);

		/* Add frames to dialog */
		frame_vbox.pack_start (sprite_layout_frame);
		frame_vbox.pack_start (sprite_size_frame);
		frame_vbox.pack_start (transparency_frame);
		frame_vbox.pack_start (header_frame);
		vbox.pack_start (frame_vbox, true, true, 8);
		vbox.show_all ();

		/* Add button. */
		add_button (STOCK_CLOSE, ResponseType.CLOSE);
		set_default_response (ResponseType.CLOSE);
	}

	/**
	 * Initialise widgets to current sprite sheet values.
	 */
	private void initialise_widgets () {
		/* Sprite layout */
		if (sprite_sheet.sprite_layout == 
									SpriteSheet.SpriteDataLayout.ROW_MAJOR) {
			layout_row_major.active = true;
		} else {
			layout_column_major.active = true;
		}

		/* Sprite size */
		if (sprite_sheet.should_break_sprites) {
			size_break.active = true;
			break_across.sensitive = true;
			break_down.sensitive = true;
			break_across_label.sensitive = true;
			break_down_label.sensitive = true;
		} else {
			size_whole.active = true;
			break_across.sensitive = false;
			break_down.sensitive = false;
			break_across_label.sensitive = false;
			break_down_label.sensitive = false;
		}
		break_across.value = sprite_sheet.sub_sprite_width;
		break_down.value = sprite_sheet.sub_sprite_height;

		/* Transparency / masking */
		if (sprite_sheet.should_export_separate_mask) {
			transparency_mask.active = true;
		} else {
			transparency_colour_0.active = true;
		}

		/* Header file generation */
		header_checkbutton.active = sprite_sheet.should_generate_header;
		syntax_entry.sensitive = sprite_sheet.should_generate_header;
		syntax_label_1.sensitive = sprite_sheet.should_generate_header;
		syntax_label_2.sensitive = sprite_sheet.should_generate_header;
		syntax_entry.text = sprite_sheet.assembler_syntax;
	}

	/**
	 * Connect signals to the widgets on the export settings dialog box.
	 */
	private void connect_signals () {
		layout_row_major.toggled.connect (on_layout_row_major_toggled);
		layout_column_major.toggled.connect (on_layout_column_major_toggled);
		size_whole.toggled.connect (on_size_whole_toggled);
		size_break.toggled.connect (on_size_break_toggled);
		break_across.value_changed.connect (on_break_across_changed);
		break_down.value_changed.connect (on_break_down_changed);
		transparency_colour_0.toggled.connect (on_colour_0_toggled);
		transparency_mask.toggled.connect (on_mask_toggled);
		header_checkbutton.toggled.connect (on_header_toggled);
		syntax_entry.changed.connect (on_entry_changed);
	}

	/**
	 * Called when the row major radio button toggled. 
	 */
	private void on_layout_row_major_toggled () {
		if (layout_row_major.active) {
			sprite_sheet.sprite_layout = 
									SpriteSheet.SpriteDataLayout.ROW_MAJOR;
		}
	}

	/**
	 * Called when the column major radio button toggled. 
	 */
	private void on_layout_column_major_toggled () {
		if (layout_column_major.active) {
			sprite_sheet.sprite_layout = 
									SpriteSheet.SpriteDataLayout.COLUMN_MAJOR;
		}
	}

	/**
	 * Called when the export sprites at defined size radio button toggled.
	 */
	private void on_size_whole_toggled () {
		if (size_whole.active) {
			sprite_sheet.should_break_sprites = false;
			break_across.sensitive = false;
			break_down.sensitive = false;
			break_across_label.sensitive = false;
			break_down_label.sensitive = false;
		}
	}

	/**
	 * Called when the export sprites broken radio button toggled.
	 */
	private void on_size_break_toggled () {
		if (size_break.active) {
			sprite_sheet.should_break_sprites = true;
			break_across.sensitive = true;
			break_down.sensitive = true;
			break_across_label.sensitive = true;
			break_down_label.sensitive = true;
		}
	}

	/**
	 * Called when the break sprites across spinbutton value changed.
	 */
	private void on_break_across_changed () {
		sprite_sheet.sub_sprite_width = (int) break_across.value;
	}

	/**
	 * Called when the break sprites down spinbutton value changed.
	 */
	private void on_break_down_changed () {
		sprite_sheet.sub_sprite_height = (int) break_down.value;
	}

	/**
	 * Called when the export mask as colour 0 radio button toggled. 
	 */
	private void on_colour_0_toggled () {
		if (transparency_colour_0.active) {
			sprite_sheet.should_export_separate_mask = false;
		}
	}

	/**
	 * Called when the export separate mask radio button toggled. 
	 */
	private void on_mask_toggled () {
		if (transparency_mask.active) {
			sprite_sheet.should_export_separate_mask = true;
		}
	}

	/**
	 * Called when the export header file check button toggled. 
	 */
	private void on_header_toggled () {
		sprite_sheet.should_generate_header = header_checkbutton.active;
		syntax_entry.sensitive = header_checkbutton.active;
		syntax_label_1.sensitive = header_checkbutton.active;
		syntax_label_2.sensitive = header_checkbutton.active;
	}

	/**
	 * Called when the export format entry box changed. 
	 */
	private void on_entry_changed () {
		sprite_sheet.assembler_syntax = syntax_entry.text;
	}
}
